part of '../widgets.dart';

class VanPopupController extends VanCtrl<bool> {
  VanPopupController([super.show = false]);

  bool get show => value;

  set show(bool show) => value = show;
}

enum VanPopupPosition { center, top, bottom, right, left }

class VanPopup extends StatefulWidget {
  /// props - 是否显示弹出层(默认: false)
  final bool? show;

  /// props - 控制器
  final VanPopupController? controller;

  /// props - 是否显示遮罩层(默认: true)
  final bool overlay;

  /// props - 弹出位置，可选值为 top bottom right left(默认: center)
  final VanPopupPosition position;

  /// props - 自定义遮罩层类名
  final String? overlayClass;

  /// props - 自定义遮罩层样式
  final String? overlayStyle;

  /// props - 动画时长，单位秒，设置为 0 可以禁用动画(默认: 0.3)
  final String duration;

  /// props - 将弹窗的 z-index 层级设置为一个固定值(默认: 2000+)
  final String zIndex;

  /// props - 是否显示圆角(默认: false)
  final bool round;

  /// props - 是否锁定背景滚动(默认: true)
  final bool lockScroll;

  /// props - 是否在显示弹层时才渲染节点(默认: true)
  final bool lazyRender;

  /// props - 是否在页面回退时自动关闭(默认: false)
  final bool closeOnPopstate;

  /// props - 是否在点击遮罩层后关闭(默认: true)
  final bool closeOnClickOverlay;

  /// props - 是否显示关闭图标(默认: false)
  final bool closeable;

  /// props - 关闭图标名称或图片链接，等同于 Icon 组件的 name 属性(默认: cross)
  final String closeIcon;

  /// props - 关闭图标位置，可选值为 top-left,bottom-left,bottom-right(默认: top-right)
  final String closeIconPosition;

  /// props - 关闭前的回调函数，返回 false 可阻止关闭，支持返回 Promise
  final String? beforeClose;

  /// props - 图标类名前缀，等同于 Icon 组件的 class-prefix 属性(默认: van-icon)
  final String iconPrefix;

  /// props - 动画类名，等价于 transition 的 name 属性
  final String? transition;

  /// props - 是否在初始渲染时启用过渡动画(默认: false)
  final bool transitionAppear;

  /// props - 指定挂载的节点，等同于 Teleport 组件的 to 属性
  final String? teleport;

  /// props - 是否开启顶部安全区适配(默认: false)
  final bool safeAreaInsetTop;

  /// props - 是否开启底部安全区适配(默认: false)
  final bool safeAreaInsetBottom;

  /// events - 点击弹出层时触发
  final VoidCallback? onClick;

  /// events - 点击遮罩层时触发
  final VoidCallback? onClickOverlay;

  /// events - 点击关闭图标时触发
  final VoidCallback? onClickCloseIcon;

  /// events - 打开弹出层时立即触发
  final VoidCallback? onOpen;

  /// events - 关闭弹出层时立即触发
  final VoidCallback? onClose;

  /// events - 打开弹出层且动画结束后触发
  final VoidCallback? onOpened;

  /// events - 关闭弹出层且动画结束后触发
  final VoidCallback? onClosed;

  final VanPopupStyle? style;

  /// slots - 弹窗内容
  final Widget? child;

  /// slots - 遮罩层的内容
  final Widget? overlayContent;

  const VanPopup({
    super.key,
    this.show,
    this.controller,
    this.overlay = true,
    this.position = VanPopupPosition.center,
    this.overlayClass,
    this.overlayStyle,
    this.duration = "0.3",
    this.zIndex = "2000+",
    this.round = false,
    this.lockScroll = true,
    this.lazyRender = true,
    this.closeOnPopstate = false,
    this.closeOnClickOverlay = true,
    this.closeable = false,
    this.closeIcon = "cross",
    this.closeIconPosition = "top-right",
    this.beforeClose,
    this.iconPrefix = "van-icon",
    this.transition,
    this.transitionAppear = false,
    this.teleport,
    this.safeAreaInsetTop = false,
    this.safeAreaInsetBottom = false,
    this.onClick,
    this.onClickOverlay,
    this.onClickCloseIcon,
    this.onOpen,
    this.onClose,
    this.onOpened,
    this.onClosed,
    this.style,
    this.child,
    this.overlayContent,
  });

  @override
  State<VanPopup> createState() => _VanPopupState();
}

class _VanPopupState extends State<VanPopup> {
  late final VanPopupController controller;
  Function(dynamic)? _onClose;

  @override
  void initState() {
    super.initState();
    controller = widget.controller ?? VanPopupController(widget.show ?? false);
  }

  VanPopupStyle getComputedStyle(BuildContext context) {
    var style = widget.style;
    if (style?.isNonNull == true) return style!;
    VanBgColor? background = style?.background;
    String? transition = style?.transition;
    BorderRadius? radius = style?.radius;
    double? closeIconSize = style?.closeIconSize;
    Color? closeIconColor = style?.closeIconColor;
    EdgeInsets? closeIconMargin = style?.closeIconMargin;
    String? closeIconZIndex = style?.closeIconZIndex;

    if (widget.round) {
      radius ??= kVanPopupRoundRadius.toBorderRadius(context);
    }

    background ??= kVanPopupBackground.toBgColor(context);
    transition ??= kVanPopupTransition.get(context);
    closeIconSize ??= kVanPopupCloseIconSize.toDouble(context);
    closeIconColor ??= kVanPopupCloseIconColor.toColor(context);
    closeIconMargin ??= kVanPopupCloseIconMargin.toEdgeInsets(context);
    closeIconZIndex ??= kVanPopupCloseIconZIndex.get(context);

    return VanPopupStyle(
      background: background,
      transition: transition,
      radius: radius,
      closeIconSize: closeIconSize,
      closeIconColor: closeIconColor,
      closeIconMargin: closeIconMargin,
      closeIconZIndex: closeIconZIndex,
    );
  }

  Widget _builder(BuildContext ctx) {
    _onClose = (value) {
      controller.value = false;
      Navigator.of(ctx).pop(value);
    };
    final style = getComputedStyle(ctx);
    List<Widget> children0 = [];
    final overlay0 = _getOverlay(ctx);
    if (overlay0 != null) children0.add(overlay0);

    if (widget.position == VanPopupPosition.center) {
      children0.add(Center(
        child: Container(
          decoration: BoxDecoration(
            color: style.background?.color,
            gradient: style.background?.gradient,
            borderRadius: style.radius,
          ),
          child: widget.child,
        ),
      ));
    }
    return Stack(children: children0);
  }

  Widget? _getOverlay(BuildContext context) {
    if (!widget.overlay) return null;

    VoidCallback? onClick0;
    if (widget.closeOnClickOverlay) {
      onClick0 = () => _onClose!(null);
    }
    if (widget.overlayContent == null) {
      return VanOverlay(onClick: onClick0);
    }

    if (onClick0 == null) return widget.overlayContent;

    return Material(
      color: Colors.transparent,
      child: InkWell(
        onTap: onClick0,
        splashColor: Colors.transparent,
        highlightColor: Colors.transparent,
        focusColor: Colors.transparent,
        hoverColor: Colors.transparent,
        enableFeedback: false,
        child: widget.overlayContent,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // Future.delayed(Duration.zero).then((value) => null)
    controller.addListener(() {
      if (!controller.show) {
        if (_onClose != null) {
          _onClose!(null);
          _onClose = null;
        }
        return;
      }
      showDialog(context: context, builder: _builder);
    });
    return ValueListenableBuilder(
        valueListenable: controller,
        builder: (ctx, show, child) {
          return Visibility(visible: false, child: Text("message:$show"));
        });
  }
}
